package com.topisv.tms.service.stock.instorage;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.EdiGoodsSku;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.stock.CusStock;
import com.topisv.tms.entity.stock.instorage.InstorageBill;
import com.topisv.tms.entity.stock.instorage.InstorageCountItem;
import com.topisv.tms.entity.stock.instorage.InstorageInfo;
import com.topisv.tms.entity.stock.instorage.InstorageLog;
import com.topisv.tms.entity.stock.instorage.InstorageUpSubTaskItem;
import com.topisv.tms.entity.stock.instorage.InstorageUpTask;
import com.topisv.tms.entity.stock.instorage.InstorageUpTaskItem;
import com.topisv.tms.entity.stock.instorage.pre.InstorageBillPre;
import com.topisv.tms.entity.work.ExceptionOrder.ExceptionOrder;
import com.topisv.tms.exception.ErrorCode;
import com.topisv.tms.exception.InStorageBillErrorCode;
import com.topisv.tms.exception.PaiUException;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.EdiGoodsSkuDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.edb.EdbInOutStoreDao;
import com.topisv.tms.repository.edb.EdbTaskDao;
import com.topisv.tms.repository.stock.CusStockDao;
import com.topisv.tms.repository.stock.instorage.InstorageBillDao;
import com.topisv.tms.repository.stock.instorage.InstorageCountItemDao;
import com.topisv.tms.repository.stock.instorage.InstorageInfoDao;
import com.topisv.tms.repository.stock.instorage.InstorageLogDao;
import com.topisv.tms.repository.stock.instorage.InstorageUpDispatchSubTaskItemDao;
import com.topisv.tms.repository.stock.instorage.InstorageUpTaskDao;
import com.topisv.tms.repository.stock.instorage.InstorageUpTaskItemDao;
import com.topisv.tms.repository.stock.preInstorage.InstorageBillItemPreDao;
import com.topisv.tms.repository.stock.preInstorage.InstorageBillPreDao;
import com.topisv.tms.repository.task.MdSendOutTaskDao;
import com.topisv.tms.repository.work.ExceptionOrder.ExceptionOrderDao;
import com.topisv.tms.rest.qimen.qmsend.QmRequestSender;
import com.topisv.tms.rest.qimen.qmservice.EntryOrderConfirmService;
import com.topisv.tms.service.vo.invoice.MDParam;
import com.topisv.tms.tools.StringCusUtils;
import com.topisv.tms.utils.EdiOrderUtil;
import com.topisv.tms.utils.PubUtil;
import com.topisv.tms.utils.SystemUtil;
import com.topisv.tms.utils.WmsContants;
import com.topisv.tms.utils.enums.InstorageStatusEnums;

import net.sf.json.JSONObject;

/**
 * 入库点收任务_service
 * 
 * @author ch
 *
 */
@Component
@Transactional(readOnly = true)
public class InstorageUpTaskService {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private InstorageUpTaskDao instorageUpTaskDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areaGroupDao;
	@Autowired
	private InstorageBillDao instorageBillDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private InstorageLogDao instorageLogDao;
	@Autowired
	private InstorageCountItemDao instorageCountItemDao;
	@Autowired
	private CusStockDao cusStockDao;
	@Autowired
	private InstorageInfoDao instorageInfoDao;
	@Autowired
	private ExceptionOrderDao exceptionOrderDao;
	@Autowired
	private MdSendOutTaskDao mdSendOutTaskDao;
	@Autowired
	private InstorageBillPreDao instorageBillPreDao;
	@Autowired
	private InstorageBillItemPreDao instorageBillItemPreDao;
	@Autowired
	private InstorageUpTaskItemDao instorageUpTaskItemDao;

	@Autowired
	private EdbInOutStoreDao edbInOutStoreDao;
	@Autowired
	private EdbTaskDao edbTaskDao;

	@Autowired
	private EdiGoodsSkuDao ediGoodsSkuDao;
	@Autowired
	private InstorageUpDispatchSubTaskItemDao instorageUpDispatchSubTaskItemDao;

	@Resource(type = EntryOrderConfirmService.class)
	private QmRequestSender<Map<Object, Object>> entryOrderConfirmService;

	@PersistenceContext
	private EntityManager em;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	/**
	 * 查询上架任务
	 * 
	 * @param param
	 * @return
	 */
	public List<InstorageUpTask> loadTaskByParam(Map<String, Object> param) {
		Specification<InstorageUpTask> spec = getWhereClause(param);
		List<InstorageUpTask> taskList = this.instorageUpTaskDao.findAll(spec);
		this.setDetail(taskList);
		return taskList;
	}

	private void setDetail(List<InstorageUpTask> taskList) {
		for (InstorageUpTask task : taskList) {

			// 商家
			String customerCode = task.getCustomerCode();
			Customers customer = this.customersDao.findByCustomerCode(customerCode);
			task.setCustomer(customer);

			// 仓库
			String warehouseCode = task.getWarehouseCode();
			AreaGroup warehouse = this.areaGroupDao.findByGroupCode(warehouseCode);
			task.setWarehouse(warehouse);

			// 入库单
			String billCode = task.getBillCode();
			InstorageBill bill = this.instorageBillDao.loadBillByCode(billCode);
			task.setBill(bill);

			// 作业员
			String workerUuid = task.getWorkerUuid();
			User worker = this.userDao.findByJobuuid(workerUuid);
			task.setWorker(worker);

		}
	}

	/**
	 * 查询条件封装
	 * 
	 * @param param
	 * @return
	 */
	private Specification<InstorageUpTask> getWhereClause(final Map<String, Object> param) {
		return new Specification<InstorageUpTask>() {
			@Override
			public Predicate toPredicate(Root<InstorageUpTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
				Predicate pre = cb.conjunction();

				// 商家组
				String customerCodes = (String) param.get("customerCodes");
				if (StringUtils.isNotBlank(customerCodes)) {
					String[] customerCodeSplit = customerCodes.split(":");
					ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerCodeSplit.length];
					int i = 0;
					for (String _customerCode : customerCodeSplit) {
						tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customerCode);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}

				// 仓库组
				String areagroups = (String) param.get("areagroups");
				if (StringUtils.isNotBlank(areagroups)) {
					String[] areagroupSplit = areagroups.split(":");
					ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
					int j = 0;
					for (String _areagroup : areagroupSplit) {
						areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), _areagroup);
						j++;
					}
					pre.getExpressions().add(cb.or(areagroupArray));
				}
				// 单号
				String upbillCode = (String) param.get("upbillCode");
				if (StringUtils.isNotEmpty(upbillCode)) {
					pre.getExpressions().add(cb.equal(r.get("billCode"), upbillCode));
				}
				// 状态
				String status = (String) param.get("status");
				if (StringUtils.isNotEmpty(status)) {

					if ("myTask".equals(status)) { // 我的任务
						String upstatus = (String) param.get("upstatus");
						if (StringUtils.isNotEmpty(upstatus)) {
							pre.getExpressions().add(cb.equal(r.get("status"), upstatus));
						} else {
							pre.getExpressions().add(cb.or(cb.equal(r.get("status"), "token"), cb.equal(r.get("status"), "doing")));
						}
					} else {
						pre.getExpressions().add(cb.equal(r.get("status"), status));
					}

				}

				// 作业员
				if (param.get("workerUuid") != null) {
					String workerUuid = (String) param.get("workerUuid");
					pre.getExpressions().add(cb.equal(r.get("workerUuid"), workerUuid));
				}

				return pre;
			}
		};
	}

	/**
	 * 领取任务
	 * 
	 * @param taskId
	 *            任务ID
	 * @param jobuuid
	 *            任务执行人
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String takeTask(Long taskId, String jobuuid) throws Exception {

		try {
			InstorageUpTask task = this.instorageUpTaskDao.findOne(taskId);
			InstorageBill bill = this.instorageBillDao.loadBillByCode(task.getBillCode());

			// 已取消的不能领取
			if (InstorageStatusEnums.CANCEL.getType().equals(bill.getStatus())) {
				throw new PaiUException(ErrorCode.ORDER_CANCELED_ERROR, new String[] { bill.getBillCode() });
			}

			User worker = this.userDao.findByJobuuid(jobuuid);
			Date now = new Date();

			// 任务已经领取
			String status = task.getStatus();
			if (!"undo".equals(status)) {
				return "token";
			}

			// 修改任务状态
			task.setWorkerUuid(jobuuid);
			task.setStatus("token"); // 任务状态 （undo.创建点收任务 token:领取任务 doing:点收中
										// finish.点收完成）
			this.instorageUpTaskDao.save(task);

			bill.setStatus("4");// 入库状态 （0:待登记 (调拨货品已出库，尚未入库) 1.入库登记 2.领取点收任务
								// 3.点收完成 4.领取上架任务 5.上架完成 ）
			this.instorageBillDao.save(bill);

			// 入库日志
			InstorageLog log = new InstorageLog();
			log.setBillCode(task.getBillCode());
			log.setWorkerUuid(jobuuid);
			log.setInfo(worker.getRealname() + "领取上架任务");
			log.setWorkTime(now);
			log.setWorkType("taskUpTask"); // 操作类型 ( sign.登记入库单
											// takeCountTask.领取点收任务
											// finishCount.点收完成
											// taskUpTask.领取上架任务 finishUp.上架完成 )
			this.instorageLogDao.save(log);

			return "success";

		} catch (Exception e) {
			throw new Exception(e);
		}
	}

	public InstorageUpTask loadById(Long taskId) {
		return instorageUpTaskDao.findOne(taskId);
	}

	public List<InstorageUpTask> loadById(String workUuid) {
		return instorageUpTaskDao.loadMyTask(workUuid);
	}

	public List<InstorageUpTaskItem> loadByBillCode(String billCode) {
		List<InstorageUpTaskItem> rs = new ArrayList<InstorageUpTaskItem>();
		List<InstorageUpTask> tasks = instorageUpTaskDao.loadByBillCode(billCode);
		for (InstorageUpTask task : tasks) {
			rs.addAll(instorageUpTaskItemDao.findByUpTaskCode(task.getTaskCode()));
		}
		return rs;
	}

	/**
	 * 整箱上架
	 * 
	 * @param uptaskCode
	 * @param boxCode
	 * @param stockCode
	 * @return continue: 上架成功，继续 finishing:上架成功，此任务已经完成
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String up_box(String uptaskCode, String boxCode, String stockCode) throws Exception {
		try {
			String msg = null;
			// 验证不通过
			InstorageCountItem item = this.instorageCountItemDao.loadByCondition(uptaskCode, boxCode);
			if (item == null) {
				return "error";
			}
			if ("up".equals(item.getUpStatus())) {
				return "uped";
			}
			InstorageBill bill = this.instorageBillDao.loadBillByCode(item.getBillCode());
			// 已取消的不能领取
			if (InstorageStatusEnums.CANCEL.getType().equals(bill.getStatus())) {
				return ErrorCode.ORDER_CANCELED_ERROR.getCode();
			}

			Date now = new Date();
			InstorageUpTask uptask = this.instorageUpTaskDao.loadByTaskCode(uptaskCode);
			User worker = this.userDao.findByJobuuid(uptask.getWorkerUuid());

			// 创建库存数据
			CusStock stock = null;
			stock = this.cusStockDao.loadStock(uptask.getCustomerCode(), uptask.getWarehouseCode(), stockCode, boxCode, item.getSku());
			if (stock == null) {
				stock = new CusStock();
				stock.setBoxCode(boxCode);
				stock.setSku(item.getSku());
				stock.setCustomerCode(item.getCustomerCode());
				Customers customer = this.customersDao.findByCustomerCode(item.getCustomerCode());
				stock.setCustomer(customer);
				AreaGroup warehouse = this.areaGroupDao.findByGroupCode(item.getWarehouseCode());
				stock.setWarehouse(warehouse);
				stock.setWarehouseCode(item.getWarehouseCode());
				stock.setStockCode(stockCode);
				stock.setSalesNum(0);
				stock.setUnusedNum(0);
				stock.setOrderNum(0);
				stock.setLockedNum(0);
				stock.setTransportNum(0);
				stock.setAirNum(0);
			}

			String errorFlag = item.getErrorFlag();
			if ("error".equals(errorFlag)) {
				stock.setUnusedNum(stock.getUnusedNum() + item.getNum());
			} else if ("noterror".equals(errorFlag)) {
				stock.setSalesNum(stock.getSalesNum() + item.getNum());
			}

			stock.setLastmodifyTime(now);
			stock.setLastopetator(worker);
			stock.setStockType("1");
			this.cusStockDao.save(stock);

			// 修改箱子上架状态:已上架
			item.setUpStatus("up");
			item.setUpNum(item.getNum());
			this.instorageCountItemDao.save(item);

			// 修改任务状态为：进行中
			uptask.setStatus("doing");
			this.instorageUpTaskDao.save(uptask);

			// 入库记录
			InstorageInfo info = this.instorageInfoDao.loadByUptaskCode(uptask.getTaskCode(), item.getSku());
			if (info == null) {
				info = new InstorageInfo();
				info.setCustomerCode(uptask.getCustomerCode());
				info.setWarehouseCode(uptask.getWarehouseCode());
				info.setBillCode(uptask.getBillCode());
				info.setUptaskCode(uptaskCode);
				info.setBillType(bill.getBillType());
				info.setSku(item.getSku());
				info.setOpeTime(uptask.getCreateTime());
				info.setNum(0);
				info.setErrorFlag(bill.getErrorFlag());
			}
			info.setNum(info.getNum() + item.getNum());
			this.instorageInfoDao.save(info);

			// 如果是异常单（取消单/退回件）入库，修改异常单状态为：已入库。
			String billType = bill.getBillType();
			String aboutCode = bill.getAboutCode();
			if ("cancelOrder".equals(billType) || "returnOrder".equals(billType)) {
				ExceptionOrder exceptionOrder = this.exceptionOrderDao.loadByOrderno(aboutCode);
				if (exceptionOrder != null) {
					exceptionOrder.setBackStatus("in");
					this.exceptionOrderDao.save(exceptionOrder);
				}
			}

			msg = "continue";

			// 查看同一上架任务其它箱子是否上架，如果都上架完了，修改上架任务状态：已上架
			List<InstorageCountItem> itemList = this.instorageCountItemDao.loadUnupItem(uptaskCode);
			if (itemList.size() == 0) {
				uptask.setStatus("finish");
				this.instorageUpTaskDao.save(uptask);

				// 写入库日志
				InstorageLog log = new InstorageLog();
				log.setBillCode(uptask.getBillCode());
				log.setInfo(worker.getRealname() + "完成上架任务(" + uptask.getTaskCode() + ")");
				log.setWorkerUuid(worker.getJobuuid());
				log.setWorkTime(now);
				log.setWorkType("finishUp");
				this.instorageLogDao.save(log);

				msg = "finishing";
			}

			// 查看同一入库单其它任务是否上架，如果都上架完了: 修改入库单状态; 统计入库数量
			List<InstorageUpTask> taskList = this.instorageUpTaskDao.loadUnfinishTask(uptask.getBillCode());
			if (taskList.size() == 0) {

				// 统计入库数量
				this.setInstorageBillInfo(bill);

				// 修改入库单状态
				bill.setStatus("5");
				this.instorageBillDao.save(bill);

				// 写入库日志
				InstorageLog log = new InstorageLog();
				log.setBillCode(uptask.getBillCode());
				log.setInfo("完成全部上架任务");
				log.setWorkTime(now);
				log.setWorkType("finishUp");
				this.instorageLogDao.save(log);
				// 上架完成,修改美的订单确认任务
				finishMDOutTask(uptask);

				// sendEdb(uptask.getBillCode());

			}

			return msg;

		} catch (Exception e) {
			throw e;
		}

	}

	/**
	 * 散货上架
	 * 
	 * @param uptaskCode
	 * @param sku
	 * @param stockCode
	 * @param boxCode
	 * @return
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String up_single(String uptaskCode, String sku, String stockCode, String boxCode) throws Exception {
		try {
			String msg = null;

			// 验证不通过
			InstorageUpTask uptask = this.instorageUpTaskDao.loadByTaskCode(uptaskCode);
			if (uptask == null) {
				return "error";
			}
			InstorageBill bill = this.instorageBillDao.loadBillByCode(uptask.getBillCode());
			// 已取消的不能领取
			if (InstorageStatusEnums.CANCEL.getType().equals(bill.getStatus())) {
				return ErrorCode.ORDER_CANCELED_ERROR.getCode();
			}

			List<InstorageCountItem> itemList = this.instorageCountItemDao.loadByUpTaskCode(uptaskCode);
			boolean flag = false;
			for (InstorageCountItem item : itemList) {
				// 已上架
				String _upStatus = item.getUpStatus();
				if ("up".equals(_upStatus)) {
					continue;
				}
				// 是否有匹配数据
				String _sku = item.getSku();
				if (_sku.equals(sku)) {

					// 修改上架状态
					item.setUpNum(item.getUpNum() + 1);
					if (item.getNum().equals(item.getUpNum())) {
						item.setUpStatus("up");
					} else {
						item.setUpStatus("uping");
					}
					this.instorageCountItemDao.save(item);
					flag = true;
					break;
				}
			}
			// 未找到匹配数据
			if (flag == false) {
				return "error";
			}

			Date now = new Date();
			User worker = this.userDao.findByJobuuid(uptask.getWorkerUuid());

			// 创建库存数据
			CusStock stock = null;
			stock = this.cusStockDao.loadStock(uptask.getCustomerCode(), uptask.getWarehouseCode(), stockCode, boxCode, sku);
			if (stock == null) {
				stock = new CusStock();
				stock.setBoxCode(boxCode);
				stock.setSku(sku);
				stock.setCustomerCode(uptask.getCustomerCode());
				Customers customer = this.customersDao.findByCustomerCode(uptask.getCustomerCode());
				stock.setCustomer(customer);
				AreaGroup warehouse = this.areaGroupDao.findByGroupCode(uptask.getWarehouseCode());
				stock.setWarehouse(warehouse);
				stock.setWarehouseCode(uptask.getWarehouseCode());
				stock.setStockCode(stockCode);
				stock.setUnusedNum(0);
				stock.setOrderNum(0);
				stock.setLockedNum(0);
				stock.setTransportNum(0);
				stock.setAirNum(0);
				stock.setStockType("1");
				stock.setSalesNum(0);
			}

			String errorFlag = uptask.getErrorFlag();
			if ("error".equals(errorFlag)) {
				stock.setUnusedNum(stock.getUnusedNum() + 1);
			} else if ("noterror".equals(errorFlag)) {
				stock.setSalesNum(stock.getSalesNum() + 1);
			}

			stock.setLastmodifyTime(now);
			stock.setLastopetator(worker);
			this.cusStockDao.save(stock);

			// 修改任务状态为：进行中
			uptask.setStatus("doing");
			this.instorageUpTaskDao.save(uptask);

			// 入库记录
			InstorageInfo info = this.instorageInfoDao.loadByUptaskCode(uptask.getTaskCode(), sku);
			if (info == null) {
				info = new InstorageInfo();
				info.setCustomerCode(uptask.getCustomerCode());
				info.setWarehouseCode(uptask.getWarehouseCode());
				info.setBillCode(uptask.getBillCode());
				info.setUptaskCode(uptaskCode);
				info.setSku(sku);
				info.setBillType(bill.getBillType());
				info.setOpeTime(uptask.getCreateTime());
				info.setNum(0);
				info.setErrorFlag(bill.getErrorFlag());
			}
			info.setNum(info.getNum() + 1);
			this.instorageInfoDao.save(info);

			// 如果是异常单（取消单/退回件）入库，修改异常单状态为：已入库。
			String billType = bill.getBillType();
			String aboutCode = bill.getAboutCode();
			if ("cancelOrder".equals(billType) || "returnOrder".equals(billType)) {
				ExceptionOrder exceptionOrder = this.exceptionOrderDao.loadByOrderno(aboutCode);
				if (exceptionOrder != null) {
					exceptionOrder.setBackStatus("in");
					this.exceptionOrderDao.save(exceptionOrder);
				}
			}
			msg = "continue";

			// 查看同一上架任务其它箱子是否上架，如果都上架完了，修改上架任务状态：已上架
			List<InstorageCountItem> _itemList = this.instorageCountItemDao.loadUnupItem(uptaskCode);
			if (_itemList.size() == 0) {
				uptask.setStatus("finish");
				this.instorageUpTaskDao.save(uptask);

				// 写入库日志
				InstorageLog log = new InstorageLog();
				log.setBillCode(uptask.getBillCode());
				log.setInfo(worker.getRealname() + "完成上架任务(" + uptask.getTaskCode() + ")");
				log.setWorkerUuid(worker.getJobuuid());
				log.setWorkTime(now);
				log.setWorkType("finishUp");
				this.instorageLogDao.save(log);

				msg = "finishing";
			}

			// 查看同一入库单其它任务是否上架，如果都上架完了: 修改入库单状态; 统计入库数量
			List<InstorageUpTask> taskList = this.instorageUpTaskDao.loadUnfinishTask(uptask.getBillCode());
			if (taskList.size() == 0) {

				// 统计入库数量
				this.setInstorageBillInfo(bill);

				// 修改入库单状态为:上架完成
				bill.setStatus("5");
				this.instorageBillDao.save(bill);

				// 写入库日志
				InstorageLog log = new InstorageLog();
				log.setBillCode(uptask.getBillCode());
				log.setInfo("完成全部上架任务");
				log.setWorkTime(now);
				log.setWorkType("finishUp");
				this.instorageLogDao.save(log);

				// 上架完成,修改美的订单确认任务
				finishMDOutTask(uptask);
			}

			return msg;

		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * 判断上架的SKU是否在分配上架子任务明细中
	 * 
	 *
	 * @param item
	 * @return [参数说明]
	 * @author <a href=mailto:zhangweize@nryuncang.com>zhangweize</a>
	 * @version 1.0.0
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public boolean checkUpSku(InstorageUpTaskItem item) {

		// 根据任务号查询分配上架子任务明细
		InstorageUpTask upTask = instorageUpTaskDao.loadByTaskCode(item.getUpTaskCode());

		List<InstorageUpSubTaskItem> upSubTaskItems = instorageUpDispatchSubTaskItemDao.findBySubTaskCodeAndSkuCodeNew(upTask.getSubTaskCode(), item.getSkuCode(), item.getBatchCode(), item.getProductDate(), item.getExpireDate());

		// 判断该SKU是否在分配上架子任务明细,并返回值
		if (upSubTaskItems != null && !upSubTaskItems.isEmpty()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 上架新流程
	 * 
	 * @param item
	 * @return
	 * @throws Exception
	 *             String
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void upNew(InstorageUpTaskItem item) {
		try {
			// add LiBin 201609010 上架之前，先验证是否超出分配的数量
			InstorageUpTask uptask = instorageUpTaskDao.loadByTaskCode(item.getUpTaskCode());
			InstorageUpSubTaskItem isutItem = instorageUpDispatchSubTaskItemDao.findByNew(uptask.getSubTaskCode(), item.getSkuCode(), item.getErrorFlag());

			InstorageUpTaskItem other = instorageUpTaskItemDao.findBy(item.getUpTaskCode(), item.getSkuCode(), item.getBoxCode(), item.getStockCode(), item.getErrorFlag());
			//该任务已经上架的数量
			Map<String, Object> upNumMap = instorageUpTaskItemDao.findByNew(item.getUpTaskCode(), item.getSkuCode(),  item.getErrorFlag());
			//上架后的数量
			Integer tUpNum = item.getNum() + (null==upNumMap.get("num")? 0: Integer.parseInt(upNumMap.get("num").toString()));
			
			if (other != null) {
				other.setNum(other.getNum() + item.getNum());
				if (null != isutItem && isutItem.getNum() < tUpNum) {
					throw new PaiUException(InStorageBillErrorCode.UPNUM_OVERTOP_ERROR);
				}
				instorageUpTaskItemDao.save(other);
			} else {
				if (null != isutItem && isutItem.getNum() < tUpNum) {
					throw new PaiUException(InStorageBillErrorCode.UPNUM_OVERTOP_ERROR);
				}
				instorageUpTaskItemDao.save(item);
			}
		} catch (Exception e) {
			logger.error("upNewerror", e);
			throw e;
		}
	}

	/**
	 * 完成上架 新流程
	 * 
	 * @param taskId
	 * @return String
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String finishUpTask(String uptaskCode) throws Exception {
		try {
			String msg = "finishing";
			// 验证不通过
			InstorageUpTask uptask = this.instorageUpTaskDao.loadByTaskCode(uptaskCode);
			if (uptask == null) {
				return "error";
			}
			if ("finish".equals(uptask.getStatus())) {
				return "finish";
			}
			InstorageBill bill = this.instorageBillDao.loadBillByCode(uptask.getBillCode());

			if ("5".equals(bill.getStatus())) {
				return "isEmpty";
			}

			// 已取消的不能领取
			if (InstorageStatusEnums.CANCEL.getType().equals(bill.getStatus())) {
				return ErrorCode.ORDER_CANCELED_ERROR.getCode();
			}
			List<InstorageUpSubTaskItem> uptaskitemList = this.instorageUpDispatchSubTaskItemDao.findBySubTaskCode(uptask.getSubTaskCode());
			List<InstorageUpTaskItem> upTaskItems = instorageUpTaskItemDao.findByUpTaskCode(uptaskCode);

			Map<String, Integer> countUpTaskItems = EdiOrderUtil.countUpTaskItemNew(uptaskitemList);
			Map<String, Integer> upItems = EdiOrderUtil.countInstorageUpTaskItemNew(upTaskItems);
			// 校验分配数量和上架数量
			if (!EdiOrderUtil.checkCountNumMatch(countUpTaskItems, upItems)) {
				return InStorageBillErrorCode.UP_NUM_ERROR.getCode();
			}
			List<InstorageCountItem> itemList = this.instorageCountItemDao.loadByBillCode(uptask.getBillCode());

			for (InstorageCountItem item : itemList) {
				for (InstorageUpTaskItem upTaskItem : upTaskItems) {
					if (upTaskItem.getSkuCode().equals(item.getSku()) && (upTaskItem.getBatchCode() == null ? "" : upTaskItem.getBatchCode()).equals(item.getBatchCode() == null ? "" : item.getBatchCode()) && (upTaskItem.getProductDate() == null ? "" : upTaskItem.getProductDate()).equals(item.getProductDate() == null ? "" : item.getProductDate()) && (upTaskItem.getExpireDate() == null ? "" : upTaskItem.getExpireDate()).equals(item.getExpireDate() == null ? "" : item.getExpireDate())) {
						// 修改点收 上架数量
						item.setUpNum(item.getUpNum() + upTaskItem.getNum());
						// item.setUptaskCode(uptaskCode);
						// item.setUpStatus("up");
					}
					instorageCountItemDao.save(itemList);
				}
			}

			Date now = new Date();
			User worker = this.userDao.findByJobuuid(uptask.getWorkerUuid());
			for (InstorageUpTaskItem item : upTaskItems) {
				// 创建库存数据

				// AddBy yinglei_lian 2016.09.28 判断该库位中是否已经存在商品的并且数量大于0
				// CusStock otherCusStock =
				// this.cusStockDao.LoadOtherStock(uptask.getCustomerCode(),
				// uptask.getWarehouseCode(), item.getStockCode(),
				// item.getBoxCode(), item.getSkuCode());
				CusStock otherCusStock = checkUpToOtherStock(bill.getCustomerCode(), bill.getInwarehouseCode(), item.getStockCode(), item.getBoxCode(), item.getSkuCode(), item.getBatchCode(), item.getProductDate(), item.getExpireDate());
				if (otherCusStock != null)
					throw new PaiUException(ErrorCode.REDO_INSTORAGE_UP_DISPATCH_TASK, new String[] { item.getSkuCode() + "SKU、批次号、生产日期、过期日期不匹配" });

				CusStock stock = null;
				List<CusStock> stockList = this.cusStockDao.loadStockNew(uptask.getCustomerCode(), uptask.getWarehouseCode(), item.getStockCode(), item.getBoxCode());

				for (CusStock stock2 : stockList) {
					//if (!(stock2.getSku().equals(item.getSkuCode())) || !((stock2.getBatchCode() == null ? "" : stock2.getBatchCode()).equals(item.getBatchCode() == null ? "" : item.getBatchCode())) || !((stock2.getProductDate() == null ? "" : stock2.getProductDate()).equals(item.getProductDate() == null ? "" : item.getProductDate())) || !((stock2.getExpireDate() == null ? "" : stock2.getExpireDate()).equals(item.getExpireDate() == null ? "" : item.getExpireDate()))) {
					if (!(stock2.getSku().equals(item.getSkuCode())) ) {
//						if ((stock2.getSalesNum() + stock2.getUnusedNum() + stock2.getOrderNum() + stock2.getLockedNum() + stock2.getTransportNum() + stock2.getAirNum()) != 0) {
//							throw new PaiUException(ErrorCode.REDO_INSTORAGE_UP_DISPATCH_TASK, new String[] { stock2.getSku() + "SKU、批次号、生产日期、过期日期不匹配" });
//						}
					} else {
						stock = stock2;
						break;
					}
				}

				if (stock == null) {
					stock = new CusStock();
					stock.setBoxCode(item.getBoxCode());
					stock.setSku(item.getSkuCode());
					stock.setBatchCode(item.getBatchCode());
					stock.setProductDate(item.getProductDate());
					stock.setExpireDate(item.getExpireDate());
					stock.setCustomerCode(uptask.getCustomerCode());
					Customers customer = this.customersDao.findByCustomerCode(uptask.getCustomerCode());
					stock.setCustomer(customer);
					AreaGroup warehouse = this.areaGroupDao.findByGroupCode(uptask.getWarehouseCode());
					stock.setWarehouse(warehouse);
					stock.setWarehouseCode(uptask.getWarehouseCode());
					stock.setStockCode(item.getStockCode());
					stock.setUnusedNum(0);
					stock.setOrderNum(0);
					stock.setLockedNum(0);
					stock.setTransportNum(0);
					stock.setAirNum(0);
					stock.setStockType("1");
					stock.setSalesNum(0);
				}/*
				 * else{ if(!(stock.getSku().equals(item.getSkuCode())) ||
				 * !((stock.getBatchCode() == null ? "" :
				 * stock.getBatchCode()).equals(item.getBatchCode() == null ? ""
				 * : item.getBatchCode())) || !((stock.getProductDate() == null
				 * ? "" : stock.getProductDate()).equals(item.getProductDate()
				 * == null ? "" : item.getProductDate())) ||
				 * !((stock.getExpireDate() == null ? "" :
				 * stock.getExpireDate()).equals(item.getExpireDate() == null ?
				 * "" : item.getExpireDate()))){ throw new
				 * PaiUException(ErrorCode.REDO_INSTORAGE_UP_DISPATCH_TASK, new
				 * String[] {stock.getSku() + "SKU、批次号、生产日期、过期日期不匹配"}); } }
				 */

				String errorFlag = item.getErrorFlag();
				if ("error".equals(errorFlag)) {
					stock.setUnusedNum(stock.getUnusedNum() + item.getNum());
				} else if ("noterror".equals(errorFlag)) {
					stock.setSalesNum(stock.getSalesNum() + item.getNum());
				}
				stock.setLastmodifyTime(now);
				stock.setLastopetator(worker);
				this.cusStockDao.save(stock);
				// 入库记录
				InstorageInfo info = this.instorageInfoDao.loadByUptaskCodeAndFlag(uptask.getTaskCode(), item.getSkuCode(), errorFlag);
				if (info == null) {
					info = new InstorageInfo();
					info.setCustomerCode(uptask.getCustomerCode());
					info.setWarehouseCode(uptask.getWarehouseCode());
					info.setBillCode(uptask.getBillCode());
					info.setUptaskCode(uptaskCode);
					info.setSku(item.getSkuCode());
					info.setBillType(bill.getBillType());
					info.setOpeTime(uptask.getCreateTime());
					info.setNum(0);
					info.setErrorFlag(errorFlag);
				}
				info.setNum(info.getNum() + item.getNum());
				this.instorageInfoDao.save(info);
			}

			// 如果是异常单（取消单/退回件）入库，修改异常单状态为：已入库。
			String billType = bill.getBillType();
			String aboutCode = bill.getAboutCode();
			if ("cancelOrder".equals(billType) || "returnOrder".equals(billType)) {
				ExceptionOrder exceptionOrder = this.exceptionOrderDao.loadByOrderno(aboutCode);
				if (exceptionOrder != null) {
					exceptionOrder.setBackStatus("in");
					this.exceptionOrderDao.save(exceptionOrder);
				}
			}

			uptask.setStatus("finish");
			this.instorageUpTaskDao.save(uptask);

			// 写入库日志
			InstorageLog log = new InstorageLog();
			log.setBillCode(uptask.getBillCode());
			log.setInfo(worker.getRealname() + "完成上架任务(" + uptask.getTaskCode() + ")");
			log.setWorkerUuid(worker.getJobuuid());
			log.setWorkTime(now);
			log.setWorkType("finishUp");
			this.instorageLogDao.save(log);

			// 统计入库数量
			this.setInstorageBillInfo(bill);

			// 修改入库单状态为:上架完成
			List<InstorageUpTask> upTaskList = instorageUpTaskDao.loadUnfinishTask(uptask.getBillCode());
			if (upTaskList.size() < 1) {
				bill.setStatus("5");
				this.instorageBillDao.save(bill);
				// 上架完成,修改美的订单确认任务
				finishMDOutTask(uptask);
				// sendEdb(bill.getAboutCode());
				if ("LMB".equals(bill.getCustomerCode())) {
					sendLMB(bill.getAboutCode(), uptask.getBillCode(), bill.getBillType());
				}
				try {
					ExceptionOrder eo = exceptionOrderDao.loadByOrderno(bill.getAboutCode());
					if (eo == null && !"allot".equals(bill.getBillType())) {
						// 入库单类型 (customer. 采购入库 allot.调拨入库 returnOrder：退回入库
						// preOrder: 预约入库)
						logger.info("不是取消订单上架 正常发送奇门流水。");
						Map<Object, Object> params = new HashMap<Object, Object>();
						params.put("billType", bill.getBillType());
						params.put("status", bill.getStatus());
						params.put("preCode", bill.getAboutCode());
						entryOrderConfirmService.send(params, bill.getCustomerCode());
					} else {
						logger.info("取消单上架不发送奇门流水。");
					}
				} catch (Exception e) {
					// e.printStackTrace();
					logger.error("QMSendError entryOrderConfirm : " + e);
				}
			}

			return msg;

		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * 检查to的库位上是否有其他商品 AddBy yinglei_lian 2016.09.29
	 * 
	 * @param to
	 * @return
	 */
	private CusStock checkUpToOtherStock(String customerCode, String warehouseCode, String stockCode, String boxCode, String sku, String batchCode, String productDate, String expireDate) {
//		List<CusStock> cusStocks = cusStockDao.LoadOtherStock(customerCode, warehouseCode, stockCode, boxCode, sku);// 判断是否有其他商品
//		if (cusStocks != null && cusStocks.size()>0)
//			return cusStocks.get(0);// 有其他商品 不能移库
		// 有没相同商品 但是批次、时间不同的商品
		//if ((batchCode.equals("") == false && batchCode != null) || (productDate.equals("") == false && productDate != null) || (expireDate.equals("") == false && expireDate != null)) {// 有有效期管理
		// StringCusUtils.TransNull(s)
		if ((PubUtil.isNotEmpty(batchCode) || PubUtil.isNotEmpty(productDate) || PubUtil.isNotEmpty(expireDate))) {// 有有效期管理
			List<CusStock> stockList = this.cusStockDao.loadStockNew(customerCode, warehouseCode, stockCode, boxCode);
			for (CusStock stock2 : stockList) {
				if ((stock2.getSku().equals(sku)) && (!(stock2.getBatchCode() == null ? "" : stock2.getBatchCode()).equals(batchCode == null ? "" : batchCode)) || !((stock2.getProductDate() == null ? "" : stock2.getProductDate()).equals(productDate == null ? "" : productDate)) || !((stock2.getExpireDate() == null ? "" : stock2.getExpireDate()).equals(expireDate == null ? "" : expireDate))) {
					if ((stock2.getSalesNum() + stock2.getUnusedNum() + stock2.getOrderNum() + stock2.getLockedNum() + stock2.getTransportNum() + stock2.getAirNum()) != 0) {
						return stock2;
					}
				}
			}
		}
		return null;
	}

	/**
	 * 删除上架明细
	 * 
	 * @param itemId
	 *            void
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void deleteItem(Long itemId) {
		instorageUpTaskItemDao.delete(itemId);
	}

	public List<InstorageUpTaskItem> findByTaskCode(String uptaskCode) {
		return instorageUpTaskItemDao.findByUpTaskCode(uptaskCode);
	}

	private void finishMDOutTask(InstorageUpTask uptask) {
		if (WmsContants.CUSTOMER_MID.equals(uptask.getCustomerCode())) {
			InstorageBillPre billPre = instorageBillPreDao.findByInBillCode(uptask.getBillCode());
			if (billPre != null) {
				mdSendOutTaskDao.updateDoneNum(billPre.getCustomerOrderNo(), 1);
			}
		}
	}

	public void sendEdb(String billCode) {/*
										 * EdbInOutStore edbInOutStore =
										 * edbInOutStoreDao
										 * .findByBillCode(billCode); if(null ==
										 * edbInOutStore) {
										 * logger.info("E店宝出入库消息为空:" +
										 * billCode); return; } String method =
										 * ""; TreeMap<String, String> map = new
										 * TreeMap<String, String>();
										 * if("01".equals
										 * (edbInOutStore.getOrderType())) {
										 * method = "edbInStoreConfirm";
										 * map.put("inStorage_no",
										 * edbInOutStore.getTid()); } else {
										 * method = "edbOutStoreConfirm";
										 * map.put("outStorage_no",
										 * edbInOutStore.getTid()); }
										 * 
										 * EdbTask edbTask =
										 * edbTaskDao.findTask(
										 * edbInOutStore.getCustomerCode(),
										 * edbInOutStore.getWhcode(), method);
										 * if(null == edbTask) {
										 * logger.info("E店宝出入库接口信息为空"); return;
										 * } Map<String,String> paramMap =
										 * getParam(edbTask.getParam());
										 * paramMap.putAll(map);; String result
										 * = EdbAPITool.edbInterface(edbTask,
										 * paramMap); logger.info("E店宝出入库接口返回" +
										 * result); JSONObject json =
										 * JSONObject.fromObject(result);
										 * if(json.containsKey("Success")) {
										 * edbInOutStore.setStatus("1");
										 * edbInOutStoreDao.save(edbInOutStore);
										 * }
										 */
	}

	public void sendLMB(String billCode, String rukucode, String bill_type) throws Exception {
		InstorageBillPre billPre = instorageBillPreDao.findByBillCode(billCode);
		if (null == billPre || !"LMB".equals(billPre.getCustomerCode())) {
			return;
		}
		String url = MDParam.LMB_URL_INSTORE;
		String appkey = MDParam.LMB_APPKEY;
		String keyword = MDParam.LMB_KEYWORD;
		JSONObject json = new JSONObject();
		int type = 1;
		if ("preOrder".equals(bill_type)) {
			type = 1;
			json.put("express_tid", "");
			json.put("source_tid", "");
		} else if ("returnOrder".equals(bill_type)) {
			type = 2;
			json.put("express_tid", billPre.getExpressNo());
			json.put("source_tid", billPre.getSourceOrdNo());
		}

		json.put("instore_tid", billPre.getCustomerOrderNo());
		json.put("warehouse_code", billPre.getInwarehouseCode());
		json.put("type", type + "");

		List<InstorageCountItem> itemList = this.instorageCountItemDao.loadByBillCode(rukucode);
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for (InstorageCountItem item : itemList) {
			EdiGoodsSku sku = ediGoodsSkuDao.findByCustomerCodeAndSku("LMB", item.getSku());
			Map<String, String> map = new HashMap<String, String>();
			map.put("bar_code", item.getSku());
			map.put("pro_sn", sku.getBar());
			if ("01".equalsIgnoreCase(item.getErrorFlag())) {
				map.put("instore_num", item.getNum() + "");
			} else {
				map.put("inferior_num", item.getNum() + "");
			}
			map.put("Pro_name", "");
			list.add(map);
		}
		json.put("items", list);
		String data = json.toString();
		String md5 = SystemUtil.MD5(appkey + data + keyword);
		String appsecret = SystemUtil.getBASE64(md5);

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("appkey", appkey));
		nvps.add(new BasicNameValuePair("appsecret", appsecret));
		nvps.add(new BasicNameValuePair("data", data));
		HttpClient httpClient = new DefaultHttpClient();
		org.apache.http.client.methods.HttpPost httpPost = new org.apache.http.client.methods.HttpPost(url);
		httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
		HttpResponse response;

		response = httpClient.execute(httpPost);
		logger.info("辣妈帮入库回调结果data " + response.getStatusLine().getStatusCode());
		if (response.getStatusLine().getStatusCode() == 200) {
			String result = EntityUtils.toString(response.getEntity());
			JSONObject resJson = JSONObject.fromObject(result);
			String retCode = resJson.getString("code");
			if (!"0".equals(retCode)) {
				logger.error("billCode = " + billCode + " rukucode = " + rukucode + "bill_type = " + bill_type + " url =" + url + " ret = " + retCode);
				throw new Exception("入库回调失败，返回值:" + retCode);
			}
			logger.info("辣妈帮入库回调 : " + url + "?appkey=" + appkey + "&appsecret=" + appsecret + "&data=" + data + " billCode = " + billCode + " rukucode = " + rukucode + "bill_type = " + bill_type + " url =" + url + " ret = " + retCode);
		} else {
			EntityUtils.consume(response.getEntity());
			logger.error("billCode = " + billCode + " rukucode = " + rukucode + "bill_type = " + bill_type + " url =" + url + " http status = " + response.getStatusLine().getStatusCode());
			throw new Exception("response status error: " + response.getStatusLine().getStatusCode());
		}

	}

	public Map<String, String> getParam(String param) {
		TreeMap<String, String> map = new TreeMap<String, String>();
		if ("".equals(param) || param == null) {
			return map;
		}
		String[] entrys = param.split("::");
		for (String entry : entrys) {
			String[] p = entry.split("#");
			map.put(p[0], p[1]);
		}
		return map;
	}

	/**
	 * 统计入库信息： 箱子数量，sku数量，商品数量
	 * 
	 * @param bill
	 */
	private void setInstorageBillInfo(InstorageBill bill) {

		int boxNum = 0;
		int goodsNum = 0;
		List<String> skuList = new ArrayList<String>();

		List<InstorageCountItem> itemList = this.instorageCountItemDao.loadByBillCode(bill.getBillCode());
		for (InstorageCountItem item : itemList) {

			// 箱子数量
			String instorageType = item.getInstorageType();
			if (instorageType.equals("box")) {
				boxNum++;
			}

			// 商品数量
			int num = item.getNum();
			goodsNum += num;

			// sku数量
			String sku = item.getSku();
			if (!skuList.contains(sku)) {
				skuList.add(sku);
			}
		}

		bill.setBoxNum(boxNum);
		bill.setSkuNum(skuList.size());
		bill.setGoodsNum(goodsNum);
	}

	public List<Object> recommendStock(String customerCode, String warehouseCode, String sku) {
		// 构建SQL
		StringBuilder sql = new StringBuilder();
		sql.append("select stock_code from ( ").append("select stock_code,(sales_num+unused_num+order_num+locked_num) as totalNum from cus_stock ").append(" where customer_code = ? and warehouse_code = ? and sku = ? ").append(" ) a ").append(" where a.totalNum > 0 order by a.totalNum limit 0, 1 ");
		Query query = em.createNativeQuery(sql.toString());
		query.setParameter(1, customerCode);
		query.setParameter(2, warehouseCode);
		query.setParameter(3, sku);
		return query.getResultList();
	}

	/**
	 * 获取sku批次信息
	 * 
	 * @param billCode
	 *            sku
	 * @return
	 */
	public List<Map<String, Object>> batchList(String subTaskCode, String sku) {
		String sql = "select distinct b.batch_code, b.product_date, b.expire_date" + " from instorage_up_sub_task_item b where sub_task_code = '" + subTaskCode + "' and " + " b.sku_code = '" + sku + "' order by b.product_date desc";
		return jdbcTemplate.queryForList(sql);
	}
}
